<?php
// +----------------------------------------------------------------------
// | 双擎基础框架 [ 基于ThinkLibrary扩展 ]
// +----------------------------------------------------------------------
// | 感谢ThinkLibrary原作者Anyon的封装
// +----------------------------------------------------------------------
// | Copyright (c) 2022~2024 https://www.sqm.la All rights reserved.
// +----------------------------------------------------------------------
// | Author: rotoos <87291030@qq.com>
// +----------------------------------------------------------------------
declare (strict_types=1);

namespace think\admin\service;

use think\admin\Library;
// use think\admin\model\SysOrg;
use think\admin\model\SysRelation;
// use think\admin\model\SysUser;
use think\admin\Service;
use think\db\exception\DataNotFoundException;
use think\db\exception\DbException;
use think\db\exception\ModelNotFoundException;

/**
 * 数据权限服务
 * Class DataScopeService
 * @package think\admin\service
 */
class DataScopeService extends Service
{

    /**
     * 数据范围查询
     * @return $this|void
     * @throws DataNotFoundException
     * @throws DbException
     * @throws ModelNotFoundException
     */
    public function dataRange()
    {
        if (AdminService::isSuper() || AdminService::isGlobalAdmin()) {
            return $this;
        }
        if (empty($this->setDataScope())) {
            return $this;
        }
    }

    /**
     * 获取用户ID集合
     * @return array
     * @throws DataNotFoundException
     * @throws DbException
     * @throws ModelNotFoundException
     */
    public function setDataScope(): array
    {
        return $this->getOrgUserIdsBy($this->getPermissionScope());
    }

    /**
     * 根据权限数据获取相关所有相关用户ID
     * @param array $permissionData
     * @return array
     * @throws DataNotFoundException
     * @throws DbException
     * @throws ModelNotFoundException
     */
    public function getOrgUserIdsBy(array $permissionData): array
    {
        $user = AdminService::getUser();

        if (empty($permissionData) || empty($user)) {
            return [0, '账号未分配角色，请先分配角色。', 0, 0];
        }

        $sessionKey = "getOrgUserIdsBy_" . $user['id']; // 生成唯一的会话键
        $cachedUserIds = Library::$sapp->session->get($sessionKey);

        if ($cachedUserIds) {
            return $cachedUserIds; // 返回缓存的用户ID
        }

        $node = NodeService::fullNode();
        $permissions = searchArrByValue($permissionData, 'apiUrl', $node);

        if (empty($permissions)) {
            return [0, '账号无该数据的读取权限。', 0, 0];
        }

        $userIds = [];
        $isAll = false;

        foreach ($permissions as $role) {
            switch ($role['scopeCategory']) {
                case 'SCOPE_ALL':
                    // 全部
                    $isAll = true;
                    break;
                /*case 'SCOPE_ORG_DEFINE':
                    // 自定义
                    $userIds = $this->ScopeOrgDefineByUserIds($userIds, $role['scopeDefineOrgIdList']);
                    break;
                case 'SCOPE_ORG':
                    // 本部门
                    $userIds = $this->ScopeOrgByUserIds($user['org']['id'], $user['id']);
                    break;
                case 'SCOPE_ORG_CHILD':
                    // 本部门及以下
                    $userIds = $this->ScopeOrgChildByUserIds($user['org']['id']);
                    break;*/
                case 'SCOPE_SELF':
                    // 本人
                    $userIds = $this->ScopeSelfByUserIds($user['id']);
                    break;
                case 'SCOPE_TENANT':
                    // 本租户
                    $userIds = $this->ScopeTenantByUserIds();
                    break;
                case 'SCOPE_MERCHANT':
                    // 本商户
                    $userIds = $this->ScopeMerchantByUserIds();
                    break;
                default:
                    break;
            }
            // 如果有全部数据，直接跳出
            if ($isAll) {
                break;
            }
        }

        // 将结果存储到会话中
        Library::$sapp->session->set($sessionKey, $userIds);

        return $userIds;
    }



    /**
     * 本商户下的所有用户ID
     * @return array
     * @throws DataNotFoundException
     * @throws DbException
     * @throws ModelNotFoundException
     */
    protected function ScopeMerchantByUserIds(): array
    {
        $sessionKey = "ScopeMerchantByUserIds_" . AdminService::getMerchantId();
        $cachedUserIds = Library::$sapp->session->get($sessionKey);

        if ($cachedUserIds) {
            return $cachedUserIds;
        }

        $userIds = SysRelation::getObjectIds('SYS_USER_HAS_MERCHANT', AdminService::getMerchantId());

        // 将结果存储到会话中
        Library::$sapp->session->set($sessionKey, $userIds);

        return $userIds;
    }


    /**
     * 本租户下的所有用户ID
     * @return array
     */
    protected function ScopeTenantByUserIds(): array
    {
        $tenantId = AdminService::getTenantId();
        $sessionKey = "ScopeTenantByUserIds_" . $tenantId;
        $cachedUserIds = Library::$sapp->session->get($sessionKey);

        if ($cachedUserIds) {
            return $cachedUserIds;
        }

        $merchantIds = SysRelation::getTargetIds('SYS_TENANT_HAS_MERCHANT', $tenantId);

        $merchantUserId = SysRelation::mk()
            ->where(['category' => 'SYS_USER_HAS_MERCHANT'])
            ->whereIn('target_id', $merchantIds)
            ->column('object_id');

        $tenantUserId = SysRelation::mk()
            ->where(['category' => 'SYS_TENANT_HAS_USER'])
            ->whereIn('object_id', $tenantId)
            ->column('target_id');

        $userIds = array_merge($merchantUserId, $tenantUserId);

        // 将结果存储到会话中
        Library::$sapp->session->set($sessionKey, $userIds);

        return $userIds;
    }


    /**
     * 自定义(SCOPE_ORG_DEFINE)情况下所有用户ID
     * @param array $userIds
     * @param array $scopeDefineOrgIdList
     * @return array
     */
    /*protected function ScopeOrgDefineByUserIds(array $userIds, array $scopeDefineOrgIdList): array
    {
        return array_merge($userIds, $this->getUserIdsByOrgId($scopeDefineOrgIdList));
    }*/

    /**
     * 获取UserID
     * @param array $ids
     * @return array
     */
    /*protected function getUserIdsByOrgId(array $ids): array
    {
        return SysUser::mk()->whereIn('orgId', implode(',', $ids))->column('id');
    }*/

    /**
     * 本部本所有用户ID
     * @param int $userOrgId
     * @param int $userId
     * @return array
     */
    /*protected function ScopeOrgByUserIds(int $userOrgId, int $userId): array
    {
        $orgUserIds = $userOrgId ? $this->getUserIdsByOrgId([$userOrgId]) : [];
        return array_unique(array_merge([$userId], $orgUserIds));
    }*/

    /**
     * 本部门及下属部分所有用户ID
     * @param int $userOrgId
     * @return array
     */
    /*protected function ScopeOrgChildByUserIds(int $userOrgId): array
    {
        $orgIds = $userOrgId ? SysOrg::mk()->where(['parentId' => $userOrgId])->column('id') : [];
        array_unshift($orgIds, $userOrgId);
        return $this->getUserIdsByOrgId(array_unique($orgIds));
    }*/

    /**
     * 本人权限
     * @param int $userId
     * @return int[]
     */
    protected function ScopeSelfByUserIds(int $userId): array
    {
        return [$userId];
    }

    /**
     * 根据用户的角色或用户ID获取该用户的权限
     * @return array
     * @throws DataNotFoundException
     * @throws DbException
     * @throws ModelNotFoundException
     */
    public function getPermissionScope(): array
    {
        $roleIds = AdminService::getRoles();
        $userId = AdminService::getUserId();

        $sessionKey = "getPermissionScope_" . $userId;
        $cachedPermissions = Library::$sapp->session->get($sessionKey);

        if ($cachedPermissions) {
            return $cachedPermissions;
        }

        $permissions = [];

        $query = SysRelation::mk()->where(function ($query) use ($roleIds, $userId) {
            if (!empty($roleIds)) {
                $query->where(['category' => 'SYS_ROLE_HAS_PERMISSION'])
                    ->whereIn('object_id', $roleIds);
            } else {
                $query->where(['category' => 'SYS_USER_HAS_PERMISSION'])
                    ->where(['object_id' => $userId]);
            }
        });

        $permissions = $query->select()->toArray();

        $permissionData = [];

        foreach ($permissions as $v) {
            $extJson = json_decode($v['extJson'], true);
            $apiUrl = isset($extJson['apiUrl']) ? NodeService::fullNode($extJson['apiUrl']) : $v['targetId'];
            $scopeCategory = $extJson['scopeCategory'] ?? 'SCOPE_SELF';
            $scopeDefineOrgIdList = $extJson['scopeDefineOrgIdList'] ?? [];
            $scopeDefineOrgIdText = implode(',', $scopeDefineOrgIdList);

            $permissionData[] = [
                'roleIds' => $roleIds,
                'apiUrl' => $apiUrl,
                'scopeCategory' => $scopeCategory,
                'scopeDefineOrgIdList' => $scopeDefineOrgIdList,
                'scopeDefineOrgIdText' => $scopeDefineOrgIdText
            ];
        }

        // 将结果存储到会话中
        Library::$sapp->session->set($sessionKey, $permissionData);

        return $permissionData;
    }


}